package edu.uba.fcen.estimacion.estimacion.graphics;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
import org.apache.log4j.Logger;

import edu.uba.fcen.estimacion.estimacion.Estimacion;
import edu.uba.fcen.estimacion.estimacion.EstimacionData;
import edu.uba.fcen.estimacion.estimacion.Means;
import edu.uba.fcen.estimacion.estimacion.TestOverCiao;

public class CiaoHitsVsCantPalabras {

	private static final Logger logger = Logger.getLogger(TestOverCiao.class);
	//Estos valores fueron calculados previamente
	private static double meanOfAgrado = 0d;
	private static double totalNo = 0;
	private static double totalYes = 0;
	private static List<Double> yesHitsList = new ArrayList<Double>();
	private static List<Double> noHitsList = new ArrayList<Double>();
	private static List<Double> coverageList = new ArrayList<Double>();
	private static List<Double> totalHitsList = new ArrayList<Double>();
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String pathToCSV = args[0];
		String pathToCiaoDirectory = args[1];
		int limitDatabase = Integer.parseInt(args[2]);
		
		File directoryBase = new File(pathToCiaoDirectory);
		
		double twentyPercentToGuess = 0d;
		double totalFiles = 0d;
		totalFiles = calculateTotalFiles(directoryBase);
		twentyPercentToGuess = 20d;
		for (int j = 100; j <= limitDatabase; j+=100) {
			Estimacion estimacion = new Estimacion(pathToCSV, j);
			System.out.println("Se ejecuta con " + j + " palabras");
			double[] intervalToGuess = {0,twentyPercentToGuess};
			for (int i=1; i<=5; i++){
				meanOfAgrado = trainning(directoryBase, estimacion, intervalToGuess, totalFiles);
				guess(directoryBase, estimacion, intervalToGuess, totalFiles);
				intervalToGuess[0] =  intervalToGuess[0] + 20d;
				intervalToGuess[1] = intervalToGuess[1] + 20d;
			}
			estimacion.closeDB();
		}
		
		StringBuilder noHitsBuilder = new StringBuilder();
		StringBuilder yesHitsBuilder = new StringBuilder();
		StringBuilder coverageBuilder = new StringBuilder();
		StringBuilder totalHitsBuilder = new StringBuilder();
		noHitsBuilder.append("noHits = c(");
		yesHitsBuilder.append("yesHits = c(");
		coverageBuilder.append("coverage = c(");
		totalHitsBuilder.append("totalHits = c(");
		for (int k = 0; k < noHitsList.size(); k+=5) {
			DescriptiveStatistics meanCoverage = new DescriptiveStatistics();
			DescriptiveStatistics meanYesHits = new DescriptiveStatistics();
			DescriptiveStatistics meanNoHits = new DescriptiveStatistics();
			DescriptiveStatistics meanTotalHits = new DescriptiveStatistics();
			
			final List<Double> noSubList = noHitsList.subList(k, k+5);
			for (double val :noSubList) {
				meanNoHits.addValue(val);
			}
			noHitsBuilder.append(meanNoHits.getMean() + ",");
			final List<Double> yesSubList = yesHitsList.subList(k, k+5);
			for (double val :yesSubList) {
				meanYesHits.addValue(val);
			}
			yesHitsBuilder.append(meanYesHits.getMean() + ",");
			final List<Double> coverageSubList = coverageList.subList(k, k+5);
			for (double val :coverageSubList) {
				meanCoverage.addValue(val);
			}
			coverageBuilder.append(meanCoverage.getMean() + ",");
			final List<Double> totalHitsSubList = totalHitsList.subList(k, k+5);
			for (double val :totalHitsSubList) {
				meanTotalHits.addValue(val);
			}
			totalHitsBuilder.append(meanTotalHits.getMean() + ",");
		}
		System.out.println(noHitsBuilder.toString());
		System.out.println(yesHitsBuilder.toString());
		System.out.println(coverageBuilder.toString());
		System.out.println(totalHitsBuilder.toString());
	}
	
	private static void guess(File directoryBase, Estimacion estimacion,
			double[] intervalToGuess, double totalFiles) {
		DescriptiveStatistics meanCoverage = new DescriptiveStatistics();
		
		EstimacionData data;
		Means mean;
		double yesHits = 0;
		double totalOpinions = 0;
		double totalNoHere = 0;
		double totalYesHere = 0;
		double totalTest = 0;
		double noHits = 0;
		
		for(File directory : directoryBase.listFiles()) {
			if (directory.isDirectory()) {
				logger.info("processing directory: " + directory.getName());
				for(File in : directory.listFiles()) {
					if (in.getName().endsWith(".freeling")) {
						if(isIntervalGuess(totalFiles, totalOpinions, intervalToGuess)) {
							data = estimacion.runOver(in.getAbsolutePath());
							mean = data.getMeans();
							Double valueStdev = Double.valueOf(mean.getStdevAgrado());
							Double valueMean = Double.valueOf(mean.getMeanAgrado());
							if (valueStdev.isNaN() || valueMean.isNaN()) {
								System.out.println("Es NaN: " + in.getAbsolutePath());
							}
							
							if (in.getName().startsWith("yes")) {
								if (mean.getMeanAgrado() >= meanOfAgrado) {
									yesHits++;
								}
								totalYesHere++;
							}
							
							if (in.getName().startsWith("no")) {
								if (mean.getMeanAgrado() < meanOfAgrado) {
									noHits++;
								}
								totalNoHere++;
							} 
							meanCoverage.addValue(data.getCoverage());
							totalTest++;
						}
						totalOpinions++;
					}
				}
			}
		}
//		System.out.println("Guessing");
//		System.out.println("Yes hits num.: " + yesHits);
//		System.out.println("No hits num.: " + noHits);
//		System.out.println("Total Opinions: " + totalOpinions);
//		System.out.println("Yes hits %: " + ((double) (yesHits/totalYes)*100));
		yesHitsList.add((yesHits/totalYesHere)*100);
//		System.out.println("No hits %: " + ((double) (noHits/totalNo)*100));
		noHitsList.add((noHits/totalNoHere)*100);
//		System.out.println("Mean Coverage: " + meanCoverage.getMean() * 100);
		coverageList.add(meanCoverage.getMean() * 100);
		totalHitsList.add(((yesHits+noHits)/totalTest)*100);
	}

	private static double trainning(File directoryBase, Estimacion estimacion, double[] intervalToGuess, double totalFiles) {
		DescriptiveStatistics meanStatistics = new DescriptiveStatistics();
		DescriptiveStatistics stdevStatistics = new DescriptiveStatistics();
		DescriptiveStatistics meanCoverage = new DescriptiveStatistics();
		
		EstimacionData data;
		Means mean;
		double totalOpinions = 0;
		
		for(File directory : directoryBase.listFiles()) {
			if (directory.isDirectory()) {
				logger.info("processing directory: " + directory.getName());
				for(File in : directory.listFiles()) {
					if (in.getName().endsWith(".freeling")){
						if (isIntervalTrainning(totalFiles, totalOpinions, intervalToGuess)) {
							data = estimacion.runOver(in.getAbsolutePath());
							mean = data.getMeans();
							Double valueStdev = Double.valueOf(mean.getStdevAgrado());
							Double valueMean = Double.valueOf(mean.getMeanAgrado());
							if (valueStdev.isNaN() || valueMean.isNaN()) {
								System.out.println("Es NaN: " + in.getAbsolutePath());
							} else {
								meanStatistics.addValue(mean.getMeanAgrado());
								stdevStatistics.addValue(mean.getStdevAgrado());
								meanCoverage.addValue(data.getCoverage());
							}
						}
						totalOpinions++;
					}
				}
			}
		}
		return meanStatistics.getMean();
	}

	private static boolean isIntervalTrainning(double totalFiles, double totalOpinions, double[] intervalToGuess) {
		return !isIntervalGuess(totalFiles, totalOpinions, intervalToGuess);
	}

	private static boolean isIntervalGuess(double totalFiles, double totalOpinions, double[] intervalToGuess) {
		double beginInterval = (intervalToGuess[0]*totalFiles) / 100;
		double endInterval = (intervalToGuess[1]*totalFiles) / 100;
		return totalOpinions >= beginInterval && totalOpinions < endInterval;
	}

	private static double calculateTotalFiles(File directoryBase) {
		double total = 0d;
		for(File directory : directoryBase.listFiles()) {
			if (directory.isDirectory()) {
				for(File in : directory.listFiles()) {
					if (in.getName().endsWith(".freeling")) {
						total++;
						if(in.getName().startsWith("yes")) {
							totalYes++;
						}
						if(in.getName().startsWith("no")) {
							totalNo++;
						}
					}
				}
			}
		}
		return total;
	}
	
}
